package com.seafood.controller;

import com.seafood.common.Result;
import com.seafood.dto.LocationAddressDTO;
import com.seafood.service.LocationAddressService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 地址管理控制器
 * 
 * @author System
 * @since 2024-01-01
 */
@Slf4j
@RestController
@RequestMapping("/api/addresses")
@RequiredArgsConstructor
@Tag(name = "地址管理", description = "地址管理相关接口")
public class LocationAddressController {

    private final LocationAddressService locationAddressService;

    @Operation(summary = "创建地址")
    @PostMapping
    public Result<LocationAddressDTO> createAddress(@Valid @RequestBody LocationAddressDTO addressDTO) {
        log.info("创建地址请求: {}", addressDTO.getAddressName());
        
        try {
            LocationAddressDTO result = locationAddressService.createAddress(addressDTO);
            return Result.success("地址创建成功", result);
        } catch (Exception e) {
            log.error("创建地址失败", e);
            return Result.error("创建地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "更新地址")
    @PutMapping("/{id}")
    public Result<LocationAddressDTO> updateAddress(@PathVariable Long id,
                                                    @Valid @RequestBody LocationAddressDTO addressDTO) {
        log.info("更新地址请求: ID={}", id);
        
        try {
            LocationAddressDTO result = locationAddressService.updateAddress(id, addressDTO);
            return Result.success("地址更新成功", result);
        } catch (Exception e) {
            log.error("更新地址失败", e);
            return Result.error("更新地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "根据ID获取地址")
    @GetMapping("/{id}")
    public Result<LocationAddressDTO> getAddressById(@PathVariable Long id) {
        log.info("查询地址请求: ID={}", id);
        
        try {
            LocationAddressDTO result = locationAddressService.getAddressById(id);
            if (result != null) {
                return Result.success("查询成功", result);
            } else {
                return Result.error("地址不存在");
            }
        } catch (Exception e) {
            log.error("查询地址失败", e);
            return Result.error("查询地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "获取业务地址列表")
    @GetMapping("/business/{businessId}")
    public Result<List<LocationAddressDTO>> getAddressesByBusiness(
            @PathVariable Long businessId,
            @RequestParam(required = false) String addressType) {
        log.info("查询业务地址列表: businessId={}, type={}", businessId, addressType);
        
        try {
            List<LocationAddressDTO> result;
            if (addressType != null && !addressType.isEmpty()) {
                result = locationAddressService.getAddressesByBusiness(businessId, addressType);
            } else {
                result = locationAddressService.getUserAddresses(businessId);
            }
            return Result.success("查询成功", result);
        } catch (Exception e) {
            log.error("查询业务地址列表失败", e);
            return Result.error("查询业务地址列表失败：" + e.getMessage());
        }
    }

    @Operation(summary = "分页查询地址")
    @GetMapping
    public Result<Page<LocationAddressDTO>> getAddresses(
            @RequestParam(required = false) String addressType,
            @RequestParam(required = false) String keyword,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size,
            @RequestParam(defaultValue = "createdAt") String sortBy,
            @RequestParam(defaultValue = "desc") String sortDir) {
        log.info("分页查询地址: type={}, keyword={}, page={}, size={}", addressType, keyword, page, size);
        
        try {
            Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
            Pageable pageable = PageRequest.of(page, size, sort);
            
            Page<LocationAddressDTO> result;
            if (keyword != null && !keyword.isEmpty()) {
                result = locationAddressService.searchAddresses(keyword, pageable);
            } else if (addressType != null && !addressType.isEmpty()) {
                result = locationAddressService.getAddressesByType(addressType, pageable);
            } else {
                return Result.error("请提供查询条件");
            }
            
            return Result.success("查询成功", result);
        } catch (Exception e) {
            log.error("分页查询地址失败", e);
            return Result.error("分页查询地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "搜索附近地址")
    @GetMapping("/nearby")
    public Result<List<LocationAddressDTO>> findNearbyAddresses(
            @RequestParam BigDecimal latitude,
            @RequestParam BigDecimal longitude,
            @RequestParam(defaultValue = "5.0") Double radiusKm,
            @RequestParam String addressType) {
        log.info("搜索附近地址: lat={}, lon={}, radius={}km, type={}", 
                latitude, longitude, radiusKm, addressType);
        
        try {
            List<LocationAddressDTO> result = locationAddressService.findNearbyAddresses(
                    latitude, longitude, radiusKm, addressType);
            return Result.success("搜索成功", result);
        } catch (Exception e) {
            log.error("搜索附近地址失败", e);
            return Result.error("搜索附近地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "坐标范围查询地址")
    @GetMapping("/range")
    public Result<List<LocationAddressDTO>> findAddressesInRange(
            @RequestParam BigDecimal minLat,
            @RequestParam BigDecimal maxLat,
            @RequestParam BigDecimal minLon,
            @RequestParam BigDecimal maxLon) {
        log.info("坐标范围查询地址: lat[{}, {}], lon[{}, {}]", minLat, maxLat, minLon, maxLon);
        
        try {
            List<LocationAddressDTO> result = locationAddressService.findAddressesInRange(
                    minLat, maxLat, minLon, maxLon);
            return Result.success("查询成功", result);
        } catch (Exception e) {
            log.error("坐标范围查询地址失败", e);
            return Result.error("坐标范围查询地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "获取默认地址")
    @GetMapping("/default/{businessId}")
    public Result<LocationAddressDTO> getDefaultAddress(
            @PathVariable Long businessId,
            @RequestParam String addressType) {
        log.info("获取默认地址: businessId={}, type={}", businessId, addressType);
        
        try {
            LocationAddressDTO result = locationAddressService.getDefaultAddress(businessId, addressType);
            if (result != null) {
                return Result.success("查询成功", result);
            } else {
                return Result.error("未找到默认地址");
            }
        } catch (Exception e) {
            log.error("获取默认地址失败", e);
            return Result.error("获取默认地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "设置默认地址")
    @PutMapping("/{id}/default")
    public Result<LocationAddressDTO> setDefaultAddress(
            @PathVariable Long id,
            @RequestParam Long businessId,
            @RequestParam String addressType) {
        log.info("设置默认地址: id={}, businessId={}, type={}", id, businessId, addressType);
        
        try {
            LocationAddressDTO result = locationAddressService.setDefaultAddress(id, businessId, addressType);
            return Result.success("设置默认地址成功", result);
        } catch (Exception e) {
            log.error("设置默认地址失败", e);
            return Result.error("设置默认地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "删除地址")
    @DeleteMapping("/{id}")
    public Result<Void> deleteAddress(@PathVariable Long id) {
        log.info("删除地址请求: ID={}", id);
        
        try {
            locationAddressService.deleteAddress(id);
            return Result.success("地址删除成功", null);
        } catch (Exception e) {
            log.error("删除地址失败", e);
            return Result.error("删除地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "批量删除地址")
    @DeleteMapping("/batch")
    public Result<Void> deleteAddresses(@RequestBody List<Long> addressIds) {
        log.info("批量删除地址请求: 数量={}", addressIds.size());
        
        try {
            locationAddressService.deleteAddresses(addressIds);
            return Result.success("批量删除地址成功", null);
        } catch (Exception e) {
            log.error("批量删除地址失败", e);
            return Result.error("批量删除地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "切换地址状态")
    @PutMapping("/{id}/status")
    public Result<LocationAddressDTO> toggleAddressStatus(
            @PathVariable Long id,
            @RequestParam Boolean isActive) {
        log.info("切换地址状态: ID={}, status={}", id, isActive);
        
        try {
            LocationAddressDTO result = locationAddressService.toggleAddressStatus(id, isActive);
            return Result.success("地址状态切换成功", result);
        } catch (Exception e) {
            log.error("切换地址状态失败", e);
            return Result.error("切换地址状态失败：" + e.getMessage());
        }
    }

    @Operation(summary = "验证并丰富地址信息")
    @PostMapping("/validate")
    public Result<LocationAddressDTO> validateAndEnrichAddress(@Valid @RequestBody LocationAddressDTO addressDTO) {
        log.info("验证并丰富地址信息: {}", addressDTO.getAddressName());
        
        try {
            LocationAddressDTO result = locationAddressService.validateAndEnrichAddress(addressDTO);
            return Result.success("地址验证成功", result);
        } catch (Exception e) {
            log.error("验证地址失败", e);
            return Result.error("验证地址失败：" + e.getMessage());
        }
    }

    @Operation(summary = "获取地址统计信息")
    @GetMapping("/statistics")
    public Result<Map<String, Object>> getAddressStatistics() {
        log.info("获取地址统计信息");
        
        try {
            Map<String, Object> result = locationAddressService.getAddressStatistics();
            return Result.success("获取统计信息成功", result);
        } catch (Exception e) {
            log.error("获取地址统计信息失败", e);
            return Result.error("获取地址统计信息失败：" + e.getMessage());
        }
    }

    @Operation(summary = "导入地址数据")
    @PostMapping("/import")
    public Result<List<LocationAddressDTO>> importAddresses(@RequestBody List<LocationAddressDTO> addresses) {
        log.info("导入地址数据: 数量={}", addresses.size());
        
        try {
            List<LocationAddressDTO> result = locationAddressService.importAddresses(addresses);
            return Result.success("地址数据导入成功", result);
        } catch (Exception e) {
            log.error("导入地址数据失败", e);
            return Result.error("导入地址数据失败：" + e.getMessage());
        }
    }

    @Operation(summary = "导出地址数据")
    @GetMapping("/export")
    public Result<List<LocationAddressDTO>> exportAddresses(
            @RequestParam(required = false) String addressType,
            @RequestParam(required = false) String province,
            @RequestParam(required = false) String city) {
        log.info("导出地址数据: type={}, province={}, city={}", addressType, province, city);
        
        try {
            List<LocationAddressDTO> result = locationAddressService.exportAddresses(addressType, province, city);
            return Result.success("地址数据导出成功", result);
        } catch (Exception e) {
            log.error("导出地址数据失败", e);
            return Result.error("导出地址数据失败：" + e.getMessage());
        }
    }

    @Operation(summary = "检查重复地址")
    @GetMapping("/duplicates")
    public Result<List<LocationAddressDTO>> checkDuplicateAddresses(
            @RequestParam BigDecimal latitude,
            @RequestParam BigDecimal longitude,
            @RequestParam(required = false) Long excludeId) {
        log.info("检查重复地址: lat={}, lon={}, excludeId={}", latitude, longitude, excludeId);
        
        try {
            List<LocationAddressDTO> result = locationAddressService.checkDuplicateAddresses(
                    latitude, longitude, excludeId);
            return Result.success("检查完成", result);
        } catch (Exception e) {
            log.error("检查重复地址失败", e);
            return Result.error("检查重复地址失败：" + e.getMessage());
        }
    }
}